function createTextNode(text) {
    return {
        type: 'TEXT_ELEMENT',
        props: {
            nodeValue: text,
            children: [],
        },
    };
}

function createElement(type, props, ...children) {
    return {
        type,
        props: {
            ...props,
            children: children.map(child => {
                const isTextNode = typeof child === 'string' || typeof child === 'number';
                return isTextNode ? createTextNode(child) : child;
            }),
        },
    };
}

function render(element, container) {
    nextUnitOfWork = {
        dom: container,
        props: {
            children: [element],
        },
    };

    root = nextUnitOfWork;

    // // 根据 element 的 type 来创建 dom
    // const dom = element.type === 'TEXT_ELEMENT' ? document.createTextNode('') : document.createElement(element.type);
    // // 设置属性
    // Object.keys(element.props).forEach(name => {
    //     // 除了 children 属性，其他属性都直接设置到 dom 上
    //     if (name !== 'children') {
    //         dom[name] = element.props[name];
    //     }
    // });
    // // 递归渲染子节点
    // element.props.children.forEach(child => render(child, dom));
    // // 将 dom 添加到 container
    // container.appendChild(dom);
}

function createDom(type) {
    return type === 'TEXT_ELEMENT' ? document.createTextNode('') : document.createElement(type);
}

function updateProps(dom, props) {
    Object.keys(props).forEach(name => {
        // 除了 children 属性，其他属性都直接设置到 dom 上
        if (name !== 'children') {
            dom[name] = props[name];
        }
    });
}

function initChildren(fiber, children) {
    let prevSibling = null;
    // 拿到当前节点的所有子节点

    children.forEach((child, index) => {
        // 为每个子节点创建一个 fiber
        const newFiber = {
            type: child.type,
            props: child.props,
            parent: fiber,
            dom: null,
            child: null,
            sibling: null,
        };
        // 将新创建的 fiber 添加到 fiber 链表中
        if (index === 0) {
            fiber.child = newFiber;
        } else {
            prevSibling.sibling = newFiber;
        }
        prevSibling = newFiber;
    });
}

function performanceWorkUnit(fiber) {
    console.log('fiber ---->', fiber.type);

    const isFunctionComponent = fiber.type instanceof Function;
    if (!fiber.dom && !isFunctionComponent) {
        const dom = (fiber.dom = createDom(fiber.type));
        // fiber.parent.dom.append(dom);

        updateProps(dom, fiber.props);
    }
    const children = isFunctionComponent ? [fiber.type(fiber.props)] : fiber.props.children;
    initChildren(fiber, children);

    if (fiber.child) {
        return fiber.child;
    }
    if (fiber.sibling) {
        return fiber.sibling;
    }

    let nextFiber = fiber.parent;
    while (nextFiber) {
        if (nextFiber.sibling) {
            return nextFiber.sibling;
        }
        nextFiber = nextFiber.parent;
    }
}
let root = null;
let nextUnitOfWork = null;
function workLoop(deadline) {
    let shouldYield = false;
    while (!shouldYield && nextUnitOfWork) {
        nextUnitOfWork = performanceWorkUnit(nextUnitOfWork);
        shouldYield = deadline.timeRemaining() < 1;
    }
    // 没有下一个任务了，就证明计算结束了，将统一提交 fiber 树
    if (!nextUnitOfWork && root) {
        commitRoot(root);
    }
    requestIdleCallback(workLoop);
}

function commitRoot(root) {
    commitWork(root.child);
    // 统一提交只能执行一次，执行完就清空
    root = null;
}

function commitWork(fiber) {
    if (!fiber) {
        return;
    }

    let fiberParent = fiber.parent;
    while (!fiberParent.dom) {
        fiberParent = fiberParent.parent;
    }
    fiber.dom && fiberParent.dom.append(fiber.dom);
    // 递归提交子节点
    commitWork(fiber.child);
    // 递归提交兄弟节点
    commitWork(fiber.sibling);
}

requestIdleCallback(workLoop);

const React = {
    createElement,
    render,
};

export default React;
